package com.youlu.campus.web.group.service;

import com.youlu.campus.service.base.BaseService;
import com.youlu.campus.web.common.base.RequestContext;
import com.youlu.campus.web.group.dto.request.GroupRankingRequest;
import com.youlu.campus.web.group.dto.response.GroupRankingResponse;
import com.youlu.campus.web.group.entity.GroupUserCountPO;
import com.youlu.campus.entity.UserPO;
import com.youlu.campus.web.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zgz
 * @date 2020/11/12 14:32
 * 排行榜抽象类
 */
@Slf4j
@Service
public class GroupRankingListService extends BaseService {


    @Autowired
    private UserService userService;

    /**
     * 更新用户排行榜统计
     * @param userId 用户ID
     * @param key signSeries 连续打卡 sign 累计
     * @param value 增值
     * @return
     */
    public boolean updateUserRank(String userId, String key, Long value, String groupId){
        log.info("updateUserRank userId {} key {} value {} groupId {}", userId, key, value, groupId);
        Query query = this.createUpdateQuery(groupId);
        query.addCriteria(Criteria.where("userId").is(userId));

        FindAndModifyOptions options = new FindAndModifyOptions();
        options.upsert(true);//如果没有 则新建并返回1

        Update update = new Update();
        if (key.equals("signSeries")) {
            update.set(key+"Count", value);
        } else {
            update.inc(key + "Count", value);
        }
        update.set(key+"UpdateTime", new Date());
        update.set("deleted", false);

        Class clazz = GroupUserCountPO.class;

        mongoTemplate.findAndModify(query, update, options, clazz);
        return true;
    }

    /**
     * 查询累计打卡排行榜
     * @return
     */
    public Page<GroupRankingResponse> findSignCount(GroupRankingRequest request){
        log.info("findSignCount {}", request);
        Query query = createQuery(request.getGroupId());
        long count = mongoTemplate.count(query, GroupUserCountPO.class);
        PageRequest pageRequest = PageRequest.of(request.getPage() - 1, request.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "signCount"));
//        query.with(new Sort(Sort.Direction.ASC, "signUpdateTime"));
        List<GroupUserCountPO> countPOList = mongoTemplate.find(query.with(pageRequest), GroupUserCountPO.class);
        List<GroupRankingResponse> list = countPOList.stream().map(countPO -> {
            GroupRankingResponse response = getUserCountDTO(countPO.getUserId());
            response.setValue(countPO.getSignCount());
            return response;
        }).collect(Collectors.toList());
        return PageableExecutionUtils.getPage(list, pageRequest, () -> count);
    }

    /**
     * 查询连续打卡排行榜
     * @return
     */
    public Page<GroupRankingResponse> findSignSeriesCount(GroupRankingRequest request){
        log.info("findSignCount {}", request);
        Query query = createQuery(request.getGroupId());
        long count = mongoTemplate.count(query, GroupUserCountPO.class);
        PageRequest pageRequest = PageRequest.of(request.getPage() - 1, request.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "signSeriesCount"));
//        query.with(new Sort(Sort.Direction.ASC, "signSeriesUpdateTime"));
        List<GroupUserCountPO> countPOList = mongoTemplate.find(query.with(pageRequest), GroupUserCountPO.class);
        List<GroupRankingResponse> list = countPOList.stream().map(countPO -> {
            GroupRankingResponse response = getUserCountDTO(countPO.getUserId());
            response.setValue(countPO.getSignSeriesCount());
            return response;
        }).collect(Collectors.toList());
        return PageableExecutionUtils.getPage(list, pageRequest, () -> count);
    }

    /**
     * 我的累计打卡排行榜
     * @return
     */
    public Map<String, Object> mySignCountRank(String groupId){

        return myCountRank("signCount", "signUpdateTime", "累计打卡", groupId);
    }

    /**
     * 我的连续打卡排行榜
     * @return
     */
    public Map<String, Object> mySignSeriesCountRank(String groupId){

        return myCountRank("signSeriesCount", "signSeriesUpdateTime", "连续打卡", groupId);
    }

    private Map<String, Object> myCountRank(String param1, String param2, String param3, String groupId){
        String userId = RequestContext.getUserId();
        //1.查询我当前的信息和更新时间
        Query query = this.createQuery(groupId);
        query.addCriteria(Criteria.where("userId").is(userId));
        GroupUserCountPO po = mongoTemplate.findOne(query, GroupUserCountPO.class);
        if(po == null){
            log.info("未查询到用户排行数据，暂无排名");
            return null;
        }
        Long count = null;
        Date time = null;
        if(param1.equals("signCount")){
            count = po.getSignCount();
            time = po.getSignUpdateTime();
        }else if(param1.equals("signSeriesCount")){
            count = po.getSignSeriesCount();
            time = po.getSignSeriesUpdateTime();
        }else if(param1.equals("inviteCount")){
            count = po.getInviteCount();
            time = po.getInviteUpdateTime();
        }
        if(count == null){
            log.info("用户排行数据为空，暂无排名");
            return null;
        }
        Map<String, Object> result = new HashMap<>();
        result.put("count", count);
        //2.查询打卡天数比我大的条数
        query = this.createQuery(groupId);
        query.addCriteria(Criteria.where(param1).gt(count));
        long gcount = mongoTemplate.count(query, GroupUserCountPO.class);

        //3.查询打卡天数和我相等，更新时间比我提前的条数
        query = this.createQuery(groupId);
        query.addCriteria(Criteria.where(param1).is(count));
        if(time == null) {
            query.addCriteria(Criteria.where("createdTime").lt(po.getCreatedTime()));
        }else{
            query.addCriteria(Criteria.where(param2).lt(time));
        }
        long ecount = mongoTemplate.count(query, GroupUserCountPO.class);

        //4.条数累加
        long rank = gcount + ecount + 1;
        log.info("用户:{},{}的当前排名：{}",userId,param3,rank);
        result.put("rank", rank);
        return result;
    }

    protected Query createUpdateQuery(String groupId) {
        Query query = new Query();
        if (StringUtils.isNotBlank(groupId)) {
            query.addCriteria(Criteria.where("groupId").is(groupId));
        }
        return query;
    }

    protected Query createQuery(String groupId) {
        Query query = new Query();
        if (StringUtils.isNotBlank(groupId)) {
            query.addCriteria(Criteria.where("groupId").is(groupId));
        }
        query.addCriteria(Criteria.where("deleted").is(false));
        return query;
    }

    private GroupRankingResponse getUserCountDTO(String userId) {
        GroupRankingResponse dto = new GroupRankingResponse();
        UserPO userInfo = userService.queryUserById(userId);
        if(userInfo != null){
            dto.setNickName(userInfo.getNickName());
            dto.setAvatarUrl(userInfo.getAvatarUrl());
            dto.setUserId(userId);
        }
        return dto;
    }


}
